#include "bootpack.h"

struct FIFO8 mousefifo;

#define KEYCMD_SENDTO_MOUSE 0xd4 /* 如果往键盘控制电路发送指令0xd4，下一个数据就会自动发送给鼠标 */
#define MOUSECMD_ENABLE 0xf4

void enable_mouse(struct MOUSE_DEC *mdec)
{
	/* 激活鼠标 */
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
	/* 顺利的话，ACK(0xfa)会被送过来 */
	mdec->phase = 0; /* 等待0xfa的阶段 */
	return;
}

int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
	/* 先把最初读到的0xfa舍弃掉，之后每次从鼠标送来的数据是3个字节一组的，所以每积累到3个字节就显示在屏幕上 */
	if (mdec->phase == 0)
	{
		/* 等待鼠标的0xfa的阶段 */
		if (dat == 0xfa)
		{
			mdec->phase = 1;
		}
		return 0;
	}
	if (mdec->phase == 1)
	{
		/* 等待鼠标第一字节的阶段 */
		if ((dat & 0xc8) == 0x08)
		{ /* 判断第一字节对移动有反应的部分是否在0~3的范围内；同时还要判断第一字节对点击有反应的部分是否在8~F的范围内 */
			/* 如果第一字节正确 */
			mdec->buf[0] = dat;
			mdec->phase = 2;
		}
		return 0; /* 不在范围内则被舍去 */
	}
	if (mdec->phase == 2)
	{
		/* 等待鼠标第二字节的阶段 */
		mdec->buf[1] = dat;
		mdec->phase = 3;
		return 0;
	}
	if (mdec->phase == 3)
	{
		/* 等待鼠标第三字节的阶段 */
		mdec->buf[2] = dat;
		mdec->phase = 1;
		mdec->btn = mdec->buf[0] & 0x07; /* 鼠标键的状态放在buf[0]的低3位，0x07 = 00000111 */
		/* 下面不懂 */
		mdec->x = mdec->buf[1];
		mdec->y = mdec->buf[2];
		if ((mdec->buf[0] & 0x10) != 0)
		{
			mdec->x |= 0xffffff00;
		}
		if ((mdec->buf[0] & 0x20) != 0)
		{
			mdec->y |= 0xffffff00;
		}
		mdec->y = -mdec->y; /* 鼠标的y方向与画面符号相反 */
		return 1;
	}
	return -1; /* 应该不可能到这里来 */
}

/* 来自PS/2鼠标的中断 */
void inthandler2c(int *esp)
{
    unsigned char data;
    io_out8(PIC1_OCW2, 0x64); /* 通知PIC1 IRQ-12的受理已经完成 */
    io_out8(PIC0_OCW2, 0x62); /* 通知PIC0 IRQ-02的受理已经完成 */
    data = io_in8(PORT_KEYDAT);
    fifo8_put(&mousefifo, data);
    return;
}
